/*!
 * \file quadruple.h
 */
#ifndef _Cquadruple_H_B796D118_8F21_4EB4_88E8_0C1C57695B28_INCLUDED_
#define _Cquadruple_H_B796D118_8F21_4EB4_88E8_0C1C57695B28_INCLUDED_

#include "Lang.h"

struct COperand
{
  enum Class
  {
    VOID,
    VALUE,
    LABEL,

    MAX_CLASS,
  };

  enum Flavor
  {
    CONST,
    RVALUE,
    LVALUE,

    MAX_FLAVOR,
  };

  Class m_class;
  Lang::Type m_type;
  Flavor m_flavor;
  int m_attr;

  COperand(): m_class(VOID)
  {
  }

  COperand(Lang::Type type,Flavor flavor,int attr): m_class(VALUE),m_type(type),m_flavor(flavor),m_attr(attr)
  {
  }

  COperand(int attr): m_class(LABEL),m_attr(attr)
  {
  }

  void print(bool showVoid=false) const;

  int getAsInteger() const;
  float getAsFloat() const;

  bool isConst() const;
  bool isFloat() const;

  void makeTemp();
  static COperand composeSupertype(const COperand& a,const COperand& b);
  static COperand makeVariable(int attr);
};

/*!
 * \brief тетрада
 */
struct CQuadruple
{
  enum Operation
  {
    LVALUE, /* ссылка на область памяти */
    RVALUE, /* значение выражения */
    MUL,
    DIV,
    ADD,
    SUB,
    ASSIGN,

    MAX_OPERATION,
  };

  Operation m_operation;
  COperand m_op[3];


  CQuadruple(Operation op,
    const COperand& op1=COperand(),
    const COperand& op2=COperand(),
    const COperand& op3=COperand()): m_operation(op)
  {
    m_op[0]=op1;
    m_op[1]=op2;
    m_op[2]=op3;
  }

  void print() const;

  /*!
   * \brief ссылка на переменную
   */
  static CQuadruple makeLvalue(const COperand& op);
  /*!
   * \brief ссылка на элемент вектора
   */
  static CQuadruple makeLvalue(const COperand& op1,int op2);

  /*!
   * brief значение операнда
   */
  static CQuadruple makeRvalue(const COperand& op);
  /*!
   * \brief значение четверки
   */
  static CQuadruple makeRvalue(int op);

  /*!
   * \brief бинарная операция
   */
  static CQuadruple makeArithmetic(int op1, int operation, int op2);
  /*!
   * \brief унарная операция
   */
  static CQuadruple makeArithmetic(int operation, int op2);

  static CQuadruple makeAssignment(int op1, int operation, int op2);


  static CQuadruple makeIntegerConst(int attr)
  {
    return makeRvalue(COperand(Lang::INT,COperand::CONST,attr));
  }

  static CQuadruple makeFloatingConst(int attr)
  {
    return makeRvalue(COperand(Lang::FLOAT,COperand::CONST,attr));
  }

  static CQuadruple makeBooleanConst(int attr)
  {
    return makeRvalue(COperand(Lang::BOOL,COperand::CONST,attr));
  }
};

/*!
 * \brief поместить тетраду в список
 * \return идентификатор тетрады
 */
int pushQuadruple(const CQuadruple& q);
void popQuadruple();
/*!
 * \brief получить тетраду по идентификатору
 */
const CQuadruple& getQuadruple(int i);

int getQuadrupleCount();
int quadrupleDump();


#endif //_Cquadruple_H_B796D118_8F21_4EB4_88E8_0C1C57695B28_INCLUDED_
